package com.cskaoyan.javase._2inner._1member._1basic;

/**
 * 成员内部类怎么用?
 * 类是创建对象的模板,定义成员内部类,最终还是需要创建对象的,还是需要new对象的
 *
 * 成员内部类最重要的特点/成员内部类和外围类的关系:
 *      成员内部类可以看成外围类的一个成员。
 *      要想得到成员内部类对象，必须先创建外围类对象。
 *      这是因为: 成员内部类对象的成员变量列表中,会持有外围类对象的引用!!!
 *      成员内部类和外围类之间是强依赖关系,成员内部类依赖于外围类,反过来不成立.
 *
 * 除以上关系外,还要铭记(这不是成员内部类独有的特点):
 *      内部类和外围类之间是"好兄弟",它们之间的访问不受权限限制.
 *
 * 明确以上两点,现在来学习一下成员内部类的访问特点
 * 主要从以下四个角度研究：
 *      1.成员内部类内部访问外围类成员(重要)
 *          访问的位置: 成员内部类的成员方法中(没有静态方法)
 *          成员内部类的成员方法中存在几个对象?
 *              首先肯定存在this指向当前对象,所以必然有自身类对象
 *              除此之外还有外围类对象
 *              有两个对象
 *           既然有两个对象,那么访问外围类成员如何访问呢?
 *              直接访问,而且访问不受权限限制.
 *
 *              极端情况下,会出现外围类,成员内部类同名成员变量,那怎么办呢?
 *              语法:
 *              在成员内部类的成员方法中
 *              this指向当前自身对象
 *              外围类类名.this指向外围类对象
 *
 *
 *      2.外围类访问成员内部类成员成员(重要)
 *          访问的位置:
 *              外围类是一个普通类
 *              它有两种访问位置:
 *              成员方法以及静态方法
 *
 *          这两个访问位置是有区别的
 *              1.外围类的成员方法中访问成员内部类成员
 *              这里存在什么对象?
 *              只有this指向当前自身对象
 *              外围类对象并不依赖于成员内部类
 *              所以这里不存在成员内部类对象
 *              所以想要访问它的成员,必须创建它的对象
 *              如何创建呢?
 *              要想得到成员内部类对象，必须先创建外围类对象。
 *              在外围类对象的基础上,再创建成员内部类对象
 *              这里已经存在外围类对象了,所以可以直接创建成员内部类对象.
 *
 *              2.外围类的静态成员方法中访问成员内部类成员
 *              没有任何对象, 没有外围类对象
 *              所以这里不存在成员内部类对象
 *             所以想要访问它的成员,必须创建它的对象
 *                如何创建呢?
 *                要想得到成员内部类对象，必须先创建外围类对象。
 *               在外围类对象的基础上,再创建成员内部类对象
 *               对象创建完毕后,该咋访问就咋访问.
 *
 *      3.外部类访问成员内部类成员(多数情况下访问不到,不重要)
 *      首先访问的全程都要受权限限制
 *      其次外部类中,无论是成员方法还是静态方法
 *      都没有区别
 *
 *      4.成员内部类访问外部类成员(不重要,受权限限制)
 *          可以访问,该咋访问咋访问
 *          受权限限制.
 *
 * @since 16:00
 * @author wuguidong@cskaoyan.onaliyun.com
 */
public class Demo {
    public static void main(String[] args) {
        // 1,先创建外围类对象
        EnclosedClazz ec = new EnclosedClazz();
        // 2.在外围类对象的基础上,创建成员内部类对象
        // EnclosedClazz.Inner指明该内部类的归属
        EnclosedClazz.Inner i = ec.new Inner();

        // 以上二合一
        EnclosedClazz.Inner i2 = new EnclosedClazz().new Inner();

        System.out.println(i.a);
        // System.out.println(i.b);

    }
    public void testOutside(){

    }
}

class EnclosedClazz {
    int a;
    private int b = 10;
    static int c = 20;
    static final int D = 30;

    public void testEnclosed(){
        // 直接new创建成员内部类对象
        Inner i = new Inner();
        System.out.println(i.a);
        System.out.println(i.b);
        // 什么叫在外围类对象的基础上创建成员内部类对象?
        Inner i2 = this.new Inner();
        System.out.println(i2.b);
        System.out.println(a);
    }

    public static void testStaticEnclosed(){
        // 1,先创建外围类对象
        EnclosedClazz ec = new EnclosedClazz();
        // 2.在外围类对象的基础上,创建成员内部类对象
        Inner i = ec.new Inner();
        System.out.println(i.b);

        // 以上创建对象,二合一,用链式调用
        Inner i2 = new EnclosedClazz().new Inner();
    }

    class Inner{
        int a = 666;
        private int b = 100;
        // static int c = 200;
        static final int D = 300;
        // 成员内部类的成员方法
        public void testInner(){
            System.out.println(a);
            System.out.println(b);
            System.out.println(EnclosedClazz.this.a);
            System.out.println(EnclosedClazz.this.b);
            System.out.println(EnclosedClazz.c);
            System.out.println(EnclosedClazz.D);
            System.out.println(Inner.D);
        }
        public void test(int a){
            System.out.println(a);
            System.out.println(this.a);
            System.out.println(EnclosedClazz.this.a);
            Demo d = new Demo();
        }
    }
}